﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Text;
using System.Web.Optimization;

namespace DocManager.Infrastructure.Helpers
{
	public sealed class JavaScriptBuilder
	{
		private const string JsLinkCode = @"<script type=""text/javascript"" src=""{0}""></script>";
        private const string JsBeginOnReady = @"<script type=""text/javascript""> $(function() {";
        private const string JsEndOnReady = @"});</script>";
        private List<string> includeJsFiles = new List<string>();
        private List<string> onDocumentReadyCalls = new List<string>();

		internal JavaScriptBuilder( WebViewPage page )
		{
            this.Page = page;
		}

        public WebViewPage Page
        { get; private set; }

        public HtmlHelper Html
        { get { return this.Page.Html; } }

        public UrlHelper Url
        { get { return this.Page.Url; } }


        /// <summary>
        /// Adiciona o arquivo js que possui o mesmo nome da página
        /// </summary>
        /// <returns></returns>
        public JavaScriptBuilder ForThisPage()
        {
            string fileName = this.Page.VirtualPath;
            string extension = VirtualPathUtility.GetExtension( fileName );

            if ( String.IsNullOrEmpty( extension ) )
            {
                return this.Include( fileName );
            }
            else
            {
                return this.Include( fileName.Substring( 0, fileName.Length - extension.Length ) );
            }
        }

        /// <summary>
        /// Inclui o arquivo <paramref name="fileName"/> no final da página
        /// </summary>
        /// <param name="fileName">Endereço virtual do arquivo JS</param>
        /// <returns></returns>
		public JavaScriptBuilder Include( string fileName )
		{
            if( String.IsNullOrEmpty( fileName ))
                throw new ArgumentNullException("fileName");

            if ( fileName.EndsWith( ".js" ) )
            {
                this.includeJsFiles.Add( fileName );
            }
            else
            {
                this.includeJsFiles.Add( String.Concat( fileName, ".js" ) );
            }
            return this;
		}

        /// <summary>
        /// No onReady da página, realiza a chamada <paramref name="functionCall"/>
        /// </summary>
        /// <param name="functionCall"></param>
        /// <returns></returns>
        public JavaScriptBuilder OnReady( string functionCall )
        {
            this.onDocumentReadyCalls.Add( functionCall );
            return this;
        }

        public IHtmlString RenderBundles( params string[] filePaths )
        {
            return Scripts.Render( filePaths );
        }

        public IHtmlString RenderPage()
        {
            StringBuilder html = new StringBuilder();

            // Includes
            this.includeJsFiles.Each( link => html.AppendFormat( JsLinkCode, this.Url.Content( link ) ) );

            // OnReady calls
            if ( this.onDocumentReadyCalls.Count > 0 )
            {
                bool isDebugging = false;
#if DEBUG
                isDebugging = true;
#endif
                // abre o onready
                html.Append( JsBeginOnReady ).AppendLineIf( isDebugging );
                
                // Renderiza as chamadas
                this.onDocumentReadyCalls
                    .Each(
                        call =>
                        {
                            html
                                .Append( call )
                                .Append( ';' )
                                .AppendLineIf( isDebugging );
                        } );

                // fecha o onready
                html.Append( JsEndOnReady ).AppendLineIf( isDebugging );
            }

            if ( html.Length > 0 )
            {
                return MvcHtmlString.Create( html.ToString() );
            }
            else
            {
                return MvcHtmlString.Empty;
            }
        }
	}
}